4.1 Bourne Shell 内建命令(Bourne Shell Builtins)

下列 Shell 的内建命令都继承自 Bourne Shell。这些命令在执行时都符合 POSIX 标准的规定。

:(一个冒号)

: [arguments]

在扩展参数和执行重定向之后不做任何事情。返回状态值为零。

.(一个点号)

. filename [arguments]

在当前 Shell 的上下文中,从“filename”参数指定的文件中读取并执行命令。如果“filename”中未包含斜线“/”,则会在变量“PATH”中搜索这个文件名。当 Bash 处于非 POSIX 模式中,如果在“PATH”变量中未找到“filename”,则对当前目录进行查找。如果提供了任意个参数“arguments”,则当文件“filename”执行时,这些参数将变为位置参数。否则不会改变位置参数的值。如果开启了“-T”选项,“source”命令会继承所有的“DEBUG”捕获器;如果没有开启,会在调用“source”前后对“DEBUG”捕获器字符串进行保存和恢复,并且“source”会在执行时先释放掉 DEBUG 捕获器。如果没有开启“-T”并且源文件改变了“DEBUG”捕获器,则在“source”完成后保留这个新值。返回状态即文件中最后一条命令的退出状态,或如果没有命令执行则直接返回零。如果“filename”没有找到,或不能读取,则返回非零状态。这个内建命令等同于内建命令“source”。

break

break [n]

从“for”、“while”、“until”或“select”循环中退出。如果指定了“n”,则退出第“n”层的循环。“n”必须大于等于 1。返回状态是零,除非“n”的值小于 1。

cd

cd [-L|[-P [-e]] [-@] [directory]

将当前目录更改为命令给定的“directory”。如果在命令中未提供“directory”,则使用 Shell 变量“HOME”所提供的目录。任何附加到参数“directory”后面的参数将被忽略。如果 Shell 变量“CDPATH”存在,则使用其作为搜索路径:在“CDPATH”中的每一个目录名将用于搜索参数“directory”所代表的目录,在“CDPATH”中使用冒号“:”作为多个目录的分隔符。如果参数“directory”是以斜线开头的,则不会对“CDPATH”进行搜索。

“-P”选项出现,意味着直接进入软链接的目标目录:当使用 cd 命令进入目录时,在“directory”中处理“..”的实例之前,都会先对软链接进行解析。

默认情况下,或当使用“-L”选项时,会在“cd”命令处理“directory”中的“..”实例之后解析“directory”中的软链接。

如果“..”出现在参数“directory”中时,其会立即移除上一级路径名部分直到斜线或“directory”的开头。

如果在“-P”选项出现的同时使用了“-e”选项,在目录变更成功之后不能成功地确定当前工作目录的话,则命令会返回一个未成功状态。

如果系统支持的话,“-@”选项将关联到文件的扩展属性表示为目录。

如果目录参数是“-”,会在试图改变目录前将其转换为$OLDPWD 变量。

如果使用了“CDPATH”中的一个非空目录名,或如果第一个参数是“-”,并且改变目录是成功的,则新工作目录的绝对路径名会写入标准输出。

如果目录改变成功,则返回状态值零。否则返回非零。

continue

continue [n]

重新开始下一轮的迭代循环,循环包括“for”、“while”、“until”和“select”。如果指定了“n”,则在第“n”层循环重新开始。“n”必须大于等于 1。返回状态是 0,除非“n”小于 1。

eval

eval [arguments]

将所有参数连接成一个简单命令,之后读取它并执行。其返回状态为“eval”的退出状态。如果没有参数或参数为空,则返回状态为零。

exec

exec [-cl] [-a name] [command [arguments]]

如果提供了“command”参数,则其在不创建新进程的情况下取代 shell。如果出现了“-l”选项,则 shell 将一个横线“-”作为开头的第零个参数传递给“command”。“login”程序就是这样做的。“-c”选项使得“command”在一个空白的环境中执行。如果提供了“-a”选项,shell 会将“name”参数作为第零个参数传递给“command”。如果“command”由于某种原因不能执行,非交互 Shell 会退出,除非 shell 选项“execfail”开启。在这种情况下,则返回失败状态。如果在交互模式下文件不能执行,则 shell 返回失败。如果“exec”执行失败,其子 shell 无条件退出。如果没有给出“command”,则重定向可能会影响到当前 shell 环境。如果重定向没有出现错误,则返回状态为零;否则,返回非零状态。

exit

exit [n]

退出 shell,将状态“n”返回给父 shell。如果未指定“n”,则退出状态为最后一条执行的命令状态。在 shell 终结之前,会执行所有在“EXIT”上的捕获。

export

export [-fn] [-p] [name[=value]]

将环境中的每一个“name”标记为可传递给子进程。如果提供了“-f”选项,则所有的“name”参考为函数;否则参考为 shell 变量。“-n”选项代表不再将“name”标记为可导出的。如果没有给出“name”,或使用了“-p”选项,则列出所有已导出的变量。“-p”选项所显示的结果格式可以用于再导入。如果变量名后跟随着“=value”,则会将“value”的值赋给该变量。

返回状态是零;除非提供了一个无效的选项,或提供了一个无效的变量名,或“-f”出现后所跟随的“name”不是一个 shell 函数。

getopts

getopts optstring name [arg ...]

Shell 脚本使用“getopts”对位置参数进行解析。“optstring”包含的是可识别的选项字符;如果选项字符后跟随着一个冒号,则选项后面期望有一个参数,与选项之间用空格分开。冒号“:”和问号“?”不能用做选项字符。每一次调用“getopts”时,其会将下一个选项放入 shell 变量“name”中,如果“name”不存在则初始化它,并且下一个参数的索引会被处理存入变量“OPTIND”中。每一次调用 shell 或 shell 脚本时会将“OPTIND”初始化为 1。当一个选项需要一个参数时,“getopts”会将参数存放于变量“OPTARG”中。Shell 不会自动重置“OPTIND”变量;如果需要使用一个新参数集的话,它可以在同一 shell 调用中多次调用“getopts”之间手动重置。

当遇到最后一个选项时,“getopts”会以大于零的返回值退出。“OPTIND”设置为第一个非选项参数的索引,并且“name”设置为“?”。

“getopts”正常解析位置参数,但如果提供了做为“arg”值的更多的参数,则“getopts”将选择解析这些值。

“getopts”有两种方式报告错误。如果“optstring”的第一个字符是冒号,则使用静默报错。在一般操作中,当出现了无效选项或缺失选项参数时,会打印诊断信息。如果将变量“OPTERR”设置为 0,则不会显示出错信息,即使“optstring”第一个字母不是冒号。

如果找到一个无效选项,“getopts”把变量“name”设置为“?”。并且如果未静默,则打印出错信息并将变量“OPTARG”释放。如果处于静默状态,找到的选项字符将放入“OPTARG”中,并且不会打印诊断信息。

如果没有找到所需的参数,并且“getopts”没有处于静默,则将问号“?”置于变量“name”中并且释放变量“OPTARG”,并且打印诊断信息。如果“getopts”处于静默,冒号“:”则置于变量“name”中并且“OPTARG”设置为找到的选项字符。

hash

hash [-r] [-p filename] [-dt] [name]

每次调用“hash”命令时,其会记住将提供的完整路径名“filename”所对应的命令映射给所提供的参数“name”上。这样,在后继的调用操作中不必对该“filename”所指定的命令在环境变量“PATH”所列出的目录中进行重新搜索。任何陈旧记忆的完整路径都会被丢弃。“-p”选项会阻止路径搜索,后面所提供的“filename”就是参数“name”所对应的物理位置。“-r”选项会忘掉所有已记忆的物理位置。“-d”选项会忘掉后面所指定的每一个“name”参数的物理位置。如果出现“-t”选项,则打印每一个“name”所对应的完整路径。如果在“-t”选项后给出了多个“name”参数,则在打印散列的完整路径名前加入“name”名。“-l”选项会打印出可重新用于输入的“hash”命令格式。如果没有参数给出,或只有“-l”选项给出,则打印所有已记忆命令的信息。正常返回状态是零,除非没有找到“name”参数所对应的命令或出现了一个无效的选项。

pwd

pwd [-LP]

打印当前工作目录的绝对路径名。如果提供“-P”选项,则打印的路径名不包含软链接。如果提供“-L”选项,则打印的路径名可包含软链接。返回状态为零,除非在确定当前目录名时出错或使用了无效的选项。

readonly

readonly [-aAf] [-p] [name[=value]] ...

将每一个“name”变量标记为只读。这些“name”变量的值在后继赋值过程中是不可改变的。如果提供了“-f”选项,则每一个“name”参考为 shell 函数。“-a”选项意味着每一个“name”引用为索引数组变量;“-A”意味着引用为关联数组变量。如果两个选项同时出现,则“-A”具有高优先级。如果命令中没有出现“name”参数,或使用了“-p”选项,则打印出所有只读变量。其它选项可以用于限制输出为只读变量“name”集合的一个子集。“-p”选项,可以输出为可再用于输入的格式。如果一个变量名后跟随着“=value”,则该变量值就被设置为“value”这个值。正常返回状态为零,除非,出现了无效的选项;或“name”参数中有无效的变量或函数名;或使用“-f”选项时,提供的“name”不是一个 shell 函数。

return

return [n]

会触发 shell 函数停止执行并返回状态值“n”给其调用者。如果没有指定“n”,则返回的是该函数中最后一条命令的返回状态。如果是由捕获器控制句柄执行的“return”,用于确定返回状态的最后一条命令是捕获器句柄之前的最后执行的命令。如果是在 DEBUG 捕获期间执行的“return”,则是在“return”语句之前的由捕获器句柄执行的最后一条命令确定最后返回状态。“return”也常用于终止使用内建命令“.(source)”执行的脚本,同样也会返回“n”或脚本中最后一条命令的返回状态作为脚本的退出状态。如果指定了“n”,其返回值至少是有效的 8 位数字。在函数或脚本之后的执行恢复之前,会先执行任何关联到 RETURN 捕获器的命令。如果为“return”提供了一个非数字参数,或其用在了函数外部并且不在“.”或“source”执行脚本期间使用时,则会返回非零状态值。

shift

shift [n]

左移位置参数“n”次。从第“n+1”位到第“$#”位的位置参数改变为从第“$1”位到第“$#-n”位。释放从“$#”位到“$#-n+1”位的位置参数。“n”必须是小于等于“$#”的非负数。如果“n”是零或大于“$#”,则位置参数不会有任何改变。如果未给出“n”,则假设其为 1。正常返回状态是零,除非“n”大于“$#”或小于零。其它为非零。

test 或 [

test expr

评估条件表达式“expr”并返回一个状态 0(为真)或 1(为假)。每一个操作符和操作数必须是分开的参数。组成表达式的元素的说明请参考下面章节 6.4《Bash 条件表达式》。“test”不接受任何选项,也不接受并且忽略作为选项结尾的“—”的参数。

当使用“[”形式时,命令的最后一个参数必须是“]”。

表达式可以使用下面的操作符合成,其优先级从高到低是按列出的顺序排列。对表达式的评估依据的是参数个数。当出现 5 个或更多的参数时,才会用到操作符优先级。

表达式说明
! expr如果“expr”是假,则返回真。
( expr )返回“expr”的值。这常用于覆盖操作符的正常优先级。
expr1 -a expr2*如果“expr1”和“expr2”都为真,才返回真。
expr1 -o expr2*如果“expr1”和“expr2”其中有一个为真,则返回真。

内建命令 test 和“[”使用一组基于参数个数的规则来评估条件表达式。

参数个数说明
0 个表达式为假。
1 个当且仅当参数不为空时,表达式才为真。
2 个如果第一个参数是“!”,当且仅当第二个参数为空时,表达式才为真。如果第一个参数是一元条件操作符时(参考 6.4《Bash 条件表达式》),当一元操作符的测试为真时,表达式为真。如果第一个参数不是一个有效的一元操作符,则表达式为假。
3 个按下面列出的顺序进行条件判断:
  1. 如果第二个参数是一个二元操作符(参考 6.4《Bash 条件表达式》),则表达式的测试结果就是使用第一个和第三个参数作为操作数的二元测试结果。在有三个参数情况下,“-a”和“-o”就被认为是二元操作符。
  2. 如果第一个参数是“!”,则所得到的值就是第二个和第三个参数的双参数测试结果取反。
  3. 如果第一个参数恰好是“(”,第三个参数恰好是“)”,测试结果就是第二个参数的单参数测试结果。
  4. 其它情况,表达式结果为假。
4 个如果第一个参数是“!”,则测试结果为剩余三个参数组成的表达式测试结果取反。其它情况,表达式的解析与评估则依据上面所列出的优先级规则进行。
5 个或更多表达式的解析与评估则依据上面所列出的优先级规则进行。

当使用 test 或“[”时,操作符“<”和“>”是按 ASCII 顺序进行的字典比较。

times

times

打印 shell 及其所有子 shell 的用户和系统占用时间。返回状态始终为零。

trap

trap [-lp] [arg] [sigspec ...]

当 Shell 收到信号“sigspec”时,从“arg”中读取命令并执行。如果“arg”缺省(并且有一个单一信号“sigspec”给出)或其等于“-”,每一个指定的信号位将被重置为 shell 启动时的值。如果“arg”是空字符串,之后由每一个“sigspec”所指定的信号会被 shell 及其调用的命令忽略。如果“arg”没有出现并且给出了“-p”选项,则 shell 显示关联到每一个“sigspec”上的捕获命令。如果无参数给出,或只有“-p”选项给出,“trap”打印出可用于再次输入的,关联到每一个信号编号的命令列表。“-l”选项打印出所有信号名称及其相应编号的列表。每一个“sigspec”可以是信号名称也可以是编号。信号名称是大小写不敏感的,并且前缀“SIG”是可选的。

如果“sigspec”是 0 或 EXIT,则当 shell 退出时会执行“arg”命令。如果“sigspec”是 DEBUG,则在每一条简单命令、for 命令、case 命令、select 命令、每一个算术 for 命令和 shell 函数第一条命令执行之前会先执行“arg”命令。关于 DEBUG 捕获器的详细说明,可以参考 4.3.2 小节《内建命令 shopt》中关于 extdebug 选项的说明。如果“sigspec”是 RETURN,则“arg”命令会在 shell 函数执行完成或使用“.”或 source 执行脚本完成时执行。

如果“sigspec”是 ERR,当管道(可能是由一个简单命令组成的)、列表、或复合命令所返回的状态是非零值,都会执行“arg”命令,但会遵守下列条件。如果执行失败的命令是紧跟在“until”或“while”关键字之后的命令列表的一部分,或是跟随在“if”或“elif”保留字后的测试命令的一部分,或在一个“&&”或“||”命令列表的一部分(除了命令跟随着最终的“&&”或“||”),任意在管道中的命令但不包括最后一条,或使用“!”反转了命令返回状态,ERR 捕获器都不会执行。同样的情况也适用于 errexit (-e)选项。

在进入 shell 时被忽略的信号不能被捕获或重置。当没有被忽略的捕获信号创建之后,会在子 shell 或子 shell 环境中将其重置为原始值。

命令返回状态为零,除非“sigspec”没有指定为一个可用的信号。

umask

umask [-p] [-S] [mode]

将参数“mode”设置为 shell 进程创建文件的掩码。如果“mode”由数字开头,则将其翻译为一个八进制数字;如果不是,则翻译为一个可由“chmod”命令接受的符号化模掩码。如果省略“mode”,则打印当前掩码值。如果提供了“-S”选项并未提供“mode”参数,则打印出符号化掩码格式。如果提供了“-p”选项,并且省略了“mode”参数,则打印出来的格式是可用于重新输入的。如果成功改变了模或没有提供“mode”参数,则返回状态为零。否则返回非零。

注意,当模解释为一个八进制数,每一个掩码的数字都是被 7 减去所得到的值。因此,掩码 022 的掩算结果是权限 755。

unset

unset [-fnv] [name]

移除参数“name”所代表的变量或函数。如果给出“-v”选项,每一个“name”参考为 shell 变量,并移除该变量。如果给出“-f”选项,则“name”参考为一个 shell 函数,并且移除这个函数的定义。如果给出“-n”选项,并且“name”是一个带有“nameref”属性的变量,则只释放这个“name”变量而不会释放该变量所引用到的变量。在“-f”选项出现时“-n”选项不会起作用。如果未给出任何选项,则释放“name”参考的变量;如果没有这个名称的变量,而是函数,则释放这个函数。只读变量和只读函数是不能被释放的。一些 shell 变量如果被释放的话,会丢失其特殊行为;这些行为的说明注释在变量的单独描述中。该命令返回状态为零,除非“name”是只读的。